import os
import shutil
from core.builtin_config_module.builtin_config import BuiltInConfig
from core.utils_module.logger import ObfuscationLogger
from core.utils_module.language_utils import SUPPORTED_LANGUAGES, collect_extensions
from core.resources_module.file_fingerprint import FileFingerprintModifier


class BaseProjectCloner:
    """提供平台克隆器共享的工具方法"""

    def __init__(
        self,
        config: BuiltInConfig,
        logger: ObfuscationLogger,
        fingerprint_modifier: FileFingerprintModifier,
    ) -> None:
        self.config = config
        self.logger = logger
        self.fingerprint_modifier = fingerprint_modifier

    def _copy_project_files(self, source_path: str, target_path: str, project_type: str) -> None:
        """根据项目类型智能复制文件"""
        exclude_rules = {
            "ios": {
                "dirs": {".git", "build", "DerivedData", "Pods", "xcuserdata", ".idea"},
                "files": set(),
                "suffixes": set(),
            },
            "android": {
                "dirs": {".git", "build", ".gradle", ".idea"},
                "files": {"local.properties"},
                "suffixes": set(),
            },
            "generic": {
                "dirs": {".git", "__pycache__"},
                "files": set(),
                "suffixes": {".pyc"},
            },
        }

        rules = exclude_rules.get(project_type, exclude_rules["generic"])
        excluded_dirs = rules.get("dirs", set())
        excluded_files = rules.get("files", set())
        excluded_suffixes = rules.get("suffixes", set())

        # 定义跳过文件的条件
        def should_skip_file(filename: str) -> bool:
            if filename in excluded_files:
                return True
            return any(filename.endswith(suffix) for suffix in excluded_suffixes)

        file_count = 0
        for root, dirs, files in os.walk(source_path):
            dirs[:] = [d for d in dirs if d not in excluded_dirs]

            rel_dir = os.path.relpath(root, source_path)
            target_dir = os.path.join(target_path, "" if rel_dir == "." else rel_dir)

            if not os.path.exists(target_dir):
                os.makedirs(target_dir)

            for file in files:
                if should_skip_file(file):
                    continue
                source_file = os.path.join(root, file)
                target_file = os.path.join(target_dir, file)
                shutil.copy2(source_file, target_file)
                file_count += 1

        self.logger.log_operation("文件复制", f"复制了 {file_count} 个文件")

    def _modify_project_fingerprints(self, project_path: str, project_type: str) -> None:
        """修改项目中文件的指纹"""
        ios_extensions = set(collect_extensions(["swift", "objc"])).union(
            {".cpp", ".c", ".png", ".jpg", ".jpeg", ".gif", ".storyboard", ".xib"}
        )
        android_extensions = set(collect_extensions(["java", "kotlin"])).union(
            {".xml", ".png", ".jpg", ".jpeg", ".gif", ".webp"}
        )
        generic_extensions = set(collect_extensions(SUPPORTED_LANGUAGES)).union(
            {".py", ".js", ".ts", ".jsx", ".tsx", ".css", ".html"}
        )

        file_extensions = {
            "ios": sorted(ios_extensions),
            "android": sorted(android_extensions),
            "generic": sorted(generic_extensions),
        }

        if project_type == "generic":
            target_extensions = list(
                set(
                    file_extensions["generic"]
                    + file_extensions["ios"]
                    + file_extensions["android"]
                )
            )
        else:
            target_extensions = file_extensions.get(project_type, file_extensions["generic"])

        modified_count = 0
        for root, dirs, files in os.walk(project_path):
            dirs[:] = [d for d in dirs if d not in ["Pods", "node_modules", ".git", "build"]]

            for file in files:
                if not any(file.lower().endswith(ext) for ext in target_extensions):
                    continue
                file_path = os.path.join(root, file)
                try:
                    if self.fingerprint_modifier.modify_file_fingerprint(file_path):
                        modified_count += 1
                except Exception as exc:  # noqa: BLE001
                    self.logger.log_warning(f"无法修改文件指纹: {file_path}, 错误: {str(exc)}")

        self.logger.log_operation("指纹修改", f"修改了 {modified_count} 个文件的指纹")

    def _clean_empty_dirs(self, path: str) -> None:
        """递归清理空目录"""
        if os.path.exists(path) and os.path.isdir(path):
            if os.listdir(path):
                return
            os.rmdir(path)
            parent = os.path.dirname(path)
            if parent:
                self._clean_empty_dirs(parent)

    def _modify_fingerprints_if_needed(
        self, target_path: str, project_type: str, modify_fingerprints: bool
    ) -> None:
        if modify_fingerprints:
            self._modify_project_fingerprints(target_path, project_type)
